package com.xbongbong.pro.statistics.help;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.XbbConstant;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.helper.ReflectHelper;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.statistic.result.pojo.ChartResultPojo;
import com.xbongbong.pro.statistic.result.pojo.ChartStatisticsPojo;
import com.xbongbong.pro.statistic.result.pojo.DrillResultChartFieldInfoPojo;
import com.xbongbong.pro.statistic.result.pojo.DrillResultChartInfoPojo;
import com.xbongbong.pro.statistic.result.pojo.DrillResultPojo;
import com.xbongbong.pro.statistic.result.pojo.FieldAttrPojo;
import com.xbongbong.pro.statistic.result.pojo.dto.DiyResultDTO;
import com.xbongbong.pro.statistic.result.pojo.vo.ChartResultDetailVO;
import com.xbongbong.pro.statistic.result.pojo.vo.ResultTableVO;
import com.xbongbong.pro.statistics.pojo.PagePojo;
import com.xbongbong.saas.constant.BasicConstant;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 统计表分页结果的返回
 * @ClassName StatisticsTableHelper
 * @Author 梁鲁江
 * 创建时间 2022/4/12 15:19
 * 修改时间  2022/4/12 15:19
 **/
@Component
public class StatisticsTableHelper {
    @Resource
    private PaasRedisHelper paasRedisHelper;
    /**
     * 统计表结果构建
     * @param chartEntity
     * @param chartResultPojo
     * @param pageHelper
     * @param redisKey
     * @param result
     * @param resultTableVO
     * @return
     */
    public ResultTableVO statisticsTableConstruction(ChartEntity chartEntity, ChartResultPojo chartResultPojo, PageHelper pageHelper, String redisKey, JSONObject result, ResultTableVO resultTableVO) {
        JSONArray headChild = result.getJSONObject("head").getJSONArray("child");
        Boolean exportFlag = chartResultPojo.getExportFlag();
        exportFlag = exportFlag != null && exportFlag;

        if(exportFlag){
            resultTableVO = JSON.parseObject(result.toJSONString(), ResultTableVO.class);
            //导出不需要用这个做依据
            pageHelper.setRowsCount(1);
            resultTableVO.setRealRowsCount(1);
        }else {
            if(CollectionsUtil.isNotEmpty(chartEntity.getRowGroupAttr())){
                //右上角表头的占用 (列分组各占一行+行分组放在一行上)
                int topHead = chartEntity.getColGroupAttr().size() ;
                if(CollectionsUtil.isNotEmpty(chartEntity.getRowGroupAttr())){
                    topHead = topHead + 1;
                }
                JSONArray topHeadHeadChild = JSONArray.parseArray(JSON.toJSONString(headChild.subList(0, topHead)));
                int pageCount = 0;
                int realRowsCount = 0;
                int index = 1;
                Map<Integer, PagePojo> rowIndexResultMap = getPagePojoMap(chartResultPojo, pageHelper, redisKey, result, resultTableVO, headChild, topHead, pageCount, realRowsCount, index, chartEntity);
                //=========================上面是构建，下面是使用=======================
                realRowsCount = resultTableVO.getRealRowsCount();
                resultTableVO = getResultTableVO(pageHelper, result, topHeadHeadChild, rowIndexResultMap);
                resultTableVO.setRealRowsCount(realRowsCount);
            }else {
                //仅有列分组
                resultTableVO = JSON.parseObject(result.toJSONString(), ResultTableVO.class);
                pageHelper.setRowsCount(1);
                resultTableVO.setRealRowsCount(1);
            }
        }
        return resultTableVO;
    }

    /**
     * 行分组的拆分
     * @param chartResultPojo
     * @param pageHelper
     * @param redisKey
     * @param result
     * @param resultTableVO
     * @param headChild
     * @param topHead
     * @param pageCount
     * @param realRowsCount
     * @param index
     * @return
     */
    private Map<Integer, PagePojo> getPagePojoMap(ChartResultPojo chartResultPojo, PageHelper pageHelper, String redisKey, JSONObject result, ResultTableVO resultTableVO, JSONArray headChild, int topHead, int pageCount, int realRowsCount, int index,ChartEntity chartEntity) {
        List<ChartStatisticsPojo> rowGroupList = JSONArray.parseArray(JSON.toJSONString(headChild.subList(topHead, headChild.size())), ChartStatisticsPojo.class);
        List<ChartStatisticsPojo> pageList = new ArrayList<>();
        Map<Integer, PagePojo> rowIndexResultMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        boolean subTotal = Objects.equals(chartEntity.getSum(), 0) || Objects.equals(chartEntity.getSum(),2);
        for (ChartStatisticsPojo chartStatisticsPojo : rowGroupList) {
            pageCount = calculateTotal(chartStatisticsPojo.getChild(), pageCount);
            pageList.add(chartStatisticsPojo);
            if(pageCount >= pageHelper.getPageSize()){
                //把小计放在同一页
                if(subTotal && !chartStatisticsPojo.getIsSummary()) {
                  continue;
                }
                List<ChartStatisticsPojo> pageData = new ArrayList<>(pageList);
                PagePojo pagePojo = rowIndexResultMap.get(index);
                if(pagePojo == null){
                    pagePojo = new PagePojo();
                }
                pagePojo.setPageData(pageData);
                realRowsCount += pageCount;
                pagePojo.setStart(realRowsCount - pageCount);
                pagePojo.setEnd(realRowsCount);
                rowIndexResultMap.put(index, pagePojo);
                index++;
                pageList.clear();
                pageCount = 0;
            }
        }
        int rowsCount = rowIndexResultMap.size() * pageHelper.getPageSize();
        //最后不足页的处理
        if (CollectionsUtil.isNotEmpty(pageList)) {
            List<ChartStatisticsPojo> pageData = new ArrayList<>(pageList);
            pageCount = 0;
            for (ChartStatisticsPojo chartStatisticsPojo : pageData) {
                pageCount = calculateTotal(chartStatisticsPojo.getChild(), pageCount);
            }
            PagePojo pagePojo = rowIndexResultMap.get(index);
            if(pagePojo == null){
                pagePojo = new PagePojo();
            }
            pagePojo.setPageData(pageData);
            pagePojo.setStart(realRowsCount);
            realRowsCount += pageCount;
            pagePojo.setEnd(realRowsCount);
            rowIndexResultMap.put(index, pagePojo);
            rowsCount += pageCount;
        }
        pageHelper.setRowsCount(rowsCount);
        resultTableVO.setRealRowsCount(realRowsCount);
        if(!Objects.equals(chartResultPojo.getPageTurn(),1)){
            JSONObject redisResult = new JSONObject();
            redisResult.put("result", result);
            redisResult.put("pageHelper", pageHelper);
            redisResult.put("realRowsCount", realRowsCount);
            redisResult.put("rowIndexResultMap", rowIndexResultMap);
            paasRedisHelper.setValue(RedisPrefixConstant.STATISTICS_TABLE_CK_RESULT, redisKey,redisResult, RedisTimeConstant.TINY_DURATION);
        }
        return rowIndexResultMap;
    }

    /**
     * 构建VO
     * @param pageHelper
     * @param result
     * @param topHeadHeadChild
     * @param rowIndexResultMap
     * @return
     */
    private ResultTableVO getResultTableVO(PageHelper pageHelper, JSONObject result, JSONArray topHeadHeadChild, Map<Integer, PagePojo> rowIndexResultMap) {
        ResultTableVO resultTableVO;
        PagePojo pagePojo;
        if (pageHelper.getRowsCount() > pageHelper.getPageSize()) {
            pagePojo = rowIndexResultMap.get(pageHelper.getCurrentPageNum());
        } else {
            pagePojo = rowIndexResultMap.get(BasicConstant.ONE);
        }
        JSONArray body = result.getJSONArray("body");
        if(pagePojo != null){
            topHeadHeadChild.addAll(pagePojo.getPageData());
            subListBody(body, pagePojo.getStart(), pagePojo.getEnd());
        }
        result.getJSONObject("head").put("child", topHeadHeadChild);
        result.put("body",body);
        resultTableVO = JSON.parseObject(result.toJSONString(), ResultTableVO.class);
        return resultTableVO;
    }


    /**
     * 右侧数据的拆分
     * @param body
     * @param inStart
     * @param endSize
     */
    private void  subListBody(JSONArray body, int inStart, int endSize) {
        if (CollectionsUtil.isEmpty(body)) {
            return ;
        }
        for (int i = 0; i < body.size(); i++) {
            JSONObject json = body.getJSONObject(i);
            JSONArray child = json.getJSONArray("child");
            if (CollectionsUtil.isNotEmpty(child)) {
                subListBody(child, inStart, endSize);
            } else {
                JSONArray values = json.getJSONArray("values");
                if (CollectionsUtil.isNotEmpty(values)) {
                    if(endSize>values.size()){
                        endSize = values.size();
                    }
                    if(inStart > values.size()){
                        inStart = endSize - XbbConstant.STATISTICS_PAGE_SIZE;
                    }
                    List<Object> value = values.subList(inStart, endSize);
                    json.put("values", value);
                }
            }
        }
    }

    /**
     * 统计表缓存结果的获取
     * @param chartResultDetailVO
     * @param chartEntity
     * @param chartResultPojo
     * @param pageHelper
     * @param responseStr
     * @throws XbbException
     */
    public void statisticTableResult(ChartResultDetailVO chartResultDetailVO, ChartEntity chartEntity, ChartResultPojo chartResultPojo, PageHelper pageHelper, String responseStr) throws XbbException {
        JSONObject redisResult = JSON.parseObject(responseStr);
        ResultTableVO resultTableVO = new ResultTableVO();
        if (redisResult != null && redisResult.size() > 0) {
            JSONObject result = redisResult.getJSONObject("result");
            pageHelper = new PageHelper(chartResultPojo.getPage(),XbbConstant.STATISTICS_PAGE_SIZE);
            Integer rowsCount = redisResult.getJSONObject("pageHelper").getInteger("rowsCount");
            pageHelper.setRowsCount(rowsCount);
            Boolean exportFlag = chartResultPojo.getExportFlag();
            if(exportFlag !=null && exportFlag){
                resultTableVO = JSON.parseObject(result.toJSONString(), ResultTableVO.class);
            }else {
                //右上角表头的占用 (列分组各占一行+行分组放在一行上)
                int topHead = chartEntity.getColGroupAttr().size() ;
                if(CollectionsUtil.isNotEmpty(chartEntity.getRowGroupAttr())){
                    topHead = topHead + 1;
                }
                JSONArray headChild = result.getJSONObject("head").getJSONArray("child");
                JSONArray topHeadHeadChild = JSONArray.parseArray(JSON.toJSONString(headChild.subList(0, topHead)));
                Map<Integer, PagePojo> rowIndexResultMap  = JSON.parseObject(JSON.toJSONString(redisResult.get("rowIndexResultMap")), new TypeReference<Map<Integer, PagePojo>>(){});
                resultTableVO = getResultTableVO(pageHelper, result, topHeadHeadChild, rowIndexResultMap);
            }
            resultTableVO.setRealRowsCount(redisResult.getIntValue("realRowsCount"));
        }

        // 返回钻取的层级信息
        dealTableDrillInfo(chartEntity, chartResultPojo, resultTableVO);

        resultTableVO.setPageHelper(pageHelper);
        resultTableVO.setTableName(chartEntity.getName());
        resultTableVO.setChartType(chartEntity.getChartType());
        chartResultDetailVO.setTable(resultTableVO);
    }

    /**
     * 处理统计表的钻取层级信息，返回给前端拼接钻取条件
     */
    public void dealTableDrillInfo(ChartEntity chartEntity, ChartResultPojo chartResultPojo, ResultTableVO resultTableVO) {
        DrillResultPojo drillResultPojo = chartResultPojo.getDrillResultPojo();
        if (Objects.isNull(drillResultPojo)) {
            return;
        }
        Map<Long, DrillResultChartInfoPojo> resultChartInfoMap = drillResultPojo.getResultChartInfoMap();
        if (Objects.isNull(resultChartInfoMap) || resultChartInfoMap.isEmpty()) {
            return;
        }
        DrillResultChartInfoPojo drillResultChartInfoPojo = resultChartInfoMap.get(chartEntity.getId());
        if (Objects.isNull(drillResultChartInfoPojo)) {
            return;
        }
        resultTableVO.setDrill(drillResultChartInfoPojo.getDrillList());
    }

    /**
     * 将统计表的行列分组替换成最新的行列分组，以便后续的操作，以下参数有不懂的地方可以去ChartResultPojo对象中查看注释
     *
     * @param drillField        钻取的操作是针对行还是列
     * @param rowOrColGroupAttr 当前钻取图表的行或者列属性
     * @param diyResultDTO      自定义结果参数
     * @param chartEntity       当前图表信息
     */
    public void dealTableRowOrColAttrDrillSign(String drillField, JSONArray rowOrColGroupAttr, DiyResultDTO diyResultDTO, ChartEntity chartEntity) {
        List<FieldAttrPojo> rowOrColGroupAttrList = JSONArray.parseArray(rowOrColGroupAttr.toJSONString(), FieldAttrPojo.class);

        ChartResultPojo chartResultPojo = diyResultDTO.getChartResultPojo();
        if (Objects.isNull(chartResultPojo)) {
            return;
        }
        DrillResultPojo drillResultPojo = chartResultPojo.getDrillResultPojo();
        if (Objects.isNull(drillResultPojo)) {
            return;
        }
        Map<Long, DrillResultChartInfoPojo> resultChartInfoMap = drillResultPojo.getResultChartInfoMap();
        if (!drillResultPojo.getDrillFlag() || Objects.isNull(resultChartInfoMap) || resultChartInfoMap.isEmpty()) {
            return;
        }
        DrillResultChartInfoPojo drillResultChartInfoPojo = resultChartInfoMap.get(chartEntity.getId());
        if (Objects.isNull(drillResultChartInfoPojo)) {
            return;
        }
        Map<String, DrillResultChartFieldInfoPojo> chartFieldInfoMap = drillResultChartInfoPojo.getChartFieldInfoMap();
        if (Objects.isNull(chartFieldInfoMap) || chartFieldInfoMap.isEmpty()) {
            return;
        }
        DrillResultChartFieldInfoPojo drillResultChartFieldInfoPojo = chartFieldInfoMap.get(drillField);
        if (Objects.isNull(drillResultChartFieldInfoPojo)) {
            return;
        }

        // 需要拼接减号的集合字段，以及需要拼接表格返回结果的集合字段(也可以去对象中查看注释)
        List<FieldAttrPojo> conditionToTableList = drillResultChartFieldInfoPojo.getConditionToTableList();
        if (CollectionsUtil.isEmpty(conditionToTableList)) {
            return;
        }

        // 钻取操作之后的表头或者表体的数据
        List<FieldAttrPojo> newRowOrColGroupAttrList = new ArrayList<>();

        // 钻取后的指向字段，比如钻取层级为A -> B -> C，点击下钻B，goalDrillField为C；点击上卷B，则为A（也可以去对象中查看注释）
        FieldAttrPojo goalDrillField = drillResultChartFieldInfoPojo.getGoalDrillField();
        if (Objects.isNull(goalDrillField)) {
            return;
        }

        for (FieldAttrPojo fieldAttrPojo : rowOrColGroupAttrList) {
            String attr = fieldAttrPojo.getAttr();
            if (Objects.equals(attr, goalDrillField.getAttr())) {
                newRowOrColGroupAttrList.addAll(conditionToTableList);
            }
            newRowOrColGroupAttrList.add(fieldAttrPojo);
        }

        ReflectHelper.valueSet(chartEntity, drillField, JSON.parseArray(JSON.toJSONString(newRowOrColGroupAttrList)));
    }

    /**
     * 分组数据的数量计算
     * @param child
     * @param pageCount
     * @return void
     */
    private int calculateTotal(List<ChartStatisticsPojo> child, int pageCount) {
        if (CollectionsUtil.isEmpty(child)) {
            return pageCount+1;
        }
        for (ChartStatisticsPojo pojo : child) {
            if (CollectionsUtil.isEmpty(pojo.getChild())) {
                pageCount++;
                continue;
            }
            pageCount = calculateTotal(pojo.getChild(), pageCount);
        }
        return pageCount;
    }
}
